using System;
using System.Collections.Generic;
using System.Diagnostics;

using Atomic.Libraries;
using Atomic.Structures;

namespace Atomic.Clusters
{
	/// <summary>
	/// Represents a cluster in a cluster expansion.
	/// </summary>
	[Serializable]
	[DebuggerDisplay("{DebuggerDisplay}")]
	public class Cluster
	{
		internal Cluster(Structure lattice, IEnumerable<ClusterPoint> points, double maxDistance)
		{
			if (lattice == null || points == null)
			{
				throw new ArgumentNullException();
			}

			if (maxDistance < 0.0)
			{
				throw new ArgumentOutOfRangeException();
			}

			Lattice = lattice;
			Points = new ReadOnlyList<ClusterPoint>(Sort(points));
			MaxDistance = maxDistance;
		}

		private static IEnumerable<ClusterPoint> Sort(IEnumerable<ClusterPoint> points)
		{
			List<ClusterPoint> sortedPoints = new List<ClusterPoint>(points);
			sortedPoints.Sort(Comparer);
			return sortedPoints;
		}

		private static int Comparer(ClusterPoint p1, ClusterPoint p2)
		{
			int c = p1.Position.X.CompareTo(p2.Position.X);

			if (c == 0)
			{
				c = p1.Position.Y.CompareTo(p2.Position.Y);
			}

			if (c == 0)
			{
				c = p1.Position.Z.CompareTo(p2.Position.Z);
			}

			return c;
		}

		public override string ToString()
		{
			return string.Join(", ", new List<ClusterPoint>(Points).ConvertAll<string>(p => p.Position.ToString()));
		}

		/// <summary>
		/// The lattice the cluster is defined on.
		/// </summary>
		public Structure Lattice
		{
			get; // FIXME
			private set;
		}

		public ReadOnlyList<ClusterPoint> Points
		{
			get;
			private set;
		}

		/// <summary>
		/// The cluster function corresponding to this cluster.
		/// </summary>
		public ClusterFunction ClusterFunction
		{
			get;
			private set;
		}

		/// <summary>
		/// The maximal distance between any two cluster points. Measured in absolute coordinates (i.e. not relative to the basis).
		/// </summary>
		public double MaxDistance
		{
			get;
			private set;
		}

		private string DebuggerDisplay
		{
			get
			{
				return ToString();
			}
		}
	}
}
